package com.shunli.cterminal.service.impl;

import cn.hutool.core.util.StrUtil;
import com.shunli.cterminal.model.dto.IpInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: IpService
 * @Description: TODO
 * @Author: DAIYALU
 * @Date: 2024/9/24
 * @Version: 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class IpService {

    private final String IP_REGION_DATA_KEY = "ip2region";

    private final RedissonClient redissonClient;

    public IpInfo getRegion(String ip) {
        if(StrUtil.isBlank(ip)){
            return new IpInfo();
        }
        try {
            Searcher searcher = this.getSearcher();
            if(null == searcher){
                return new IpInfo();
            }
            // 中国|0|上海|上海市|联通；美国|0|犹他|盐湖城|0
            String regionInfo = searcher.search(ip);
            return getIpInfo(regionInfo);
        } catch (Exception e) {
            log.info("IP地址异常 ({}), {}", ip, e.getMessage());
            return new IpInfo();
        }
    }

    /**
     * 解析城市信息，国内显示城市名，国外显示国家名
     */
    private IpInfo getIpInfo(String regionInfo) {
        log.info("【IP信息】{}",regionInfo);
        if (StrUtil.isNotBlank(regionInfo)) {
            String[] cityArr = regionInfo.replace("|0", "").replace("0|", "").split("\\|");
            if (cityArr.length > 0) {
                if ("内网ip".equalsIgnoreCase(cityArr[0])) {
                    log.info("未知IP");
                    return IpInfo.builder().country("内网IP").build();
                }
                IpInfo info = new IpInfo();
                info.setCountry(cityArr[0]);
                if ("中国".equals(cityArr[0])) {
                    info.setProvince(cityArr[1]);
                    info.setCity(cityArr[2]);
                    info.setServiceProvider(cityArr[3]);
                }
                return info;
            }
        }
        log.info("未知IP");
        return new IpInfo();
    }

    public byte[] inputStreamToByteArray(InputStream inputStream) {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int num;
            while ((num = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, num);
            }
            byteArrayOutputStream.flush();
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Searcher getSearcher(){
        RBucket<byte[]> bucket = redissonClient.getBucket(IP_REGION_DATA_KEY);
        byte[] bytes = bucket.get();
        if(null != bytes){
            try{
                return Searcher.newWithBuffer(bytes);
            }catch (Exception e){
                return null;
            }
        }
        // jar包也能获取ip2region.xdb文件
        try(InputStream in = this.getClass().getClassLoader().getResourceAsStream("ip2region.xdb");){
            bytes = inputStreamToByteArray(in);
            bucket.set(bytes,30, TimeUnit.DAYS);
            return Searcher.newWithBuffer(bytes);
        }catch (Exception e){
            return null;
        }
    }
}
